--地图循环拼接
---@class MapLinkCtr
MapLinkCtr = {};
local this = MapLinkCtr;

local Str_Far="Far";
local Str_Mid="Mid";
local Str_Near = "Near";
local Str_StartPoint="StartPoint";
local Str_EndPoint ="EndPoint";
local Str_CheckPoint ="CheckPoint";

local camCamera;
local objMap;

local objFar;
local objFarNext;
local farLastCheckState;
local pointFarInit;
local pointFarNextInit

local objMid;
local objMidNext;
local midLastCheckState;
local pointMidInit;
local pointMidNextInit

local objNear;
local objNearNext;
local nearLastCheckState;
local pointNearInit;
local pointNearNextInit;

this.trans_far_check_point = nil
this.trans_far_next_check_point = nil
this.trans_mid_check_point = nil
this.trans_mid_next_check_point = nil
this.trans_near_check_point = nil
this.trans_near_next_check_point = nil

local distance = 30

local funcLoop;

function MapLinkCtr.init(map,camera)

    local function _getLayerObejct(trName)
        local tr = objMap.transform:Find(trName);
        if tr == nil then
            for i=0,objMap.transform.childCount-1 do
                tr = objMap.transform:GetChild(i):Find(trName);
                if tr~=nil then
                    return tr.gameObject;
                end
            end
        end
        return nil;
    end

    local function _createNextObject(go, cloneGo) 
        local cloneGo = cloneGo or newObject(go);
        cloneGo.name = go.name
        cloneGo.transform.parent = go.transform.parent;
        local sx,xy,sz = Util.Lua_GetLocalScaleXYZ(cloneGo, 0, 0, 0)
        Util.Lua_SetLocalScaleXYZ(cloneGo.transform,sx,xy,sz)
        local rx,ry,rz = Util.Lua_GetLocalRotationXYZ(go, 0, 0, 0)
        Util.Lua_SetLocalRotationXYZ(cloneGo, rx, ry, rz)
        this.setNextPos(go, cloneGo)
        return cloneGo
    end

    
    this.stop();

    camCamera =camera:GetComponent("Camera");
    objMap = map;

    local objTrans =  objMap.transform:GetChild(0)
    local tempObjFar = objTrans:GetChild(0)
    local tempObjMid = objTrans:GetChild(1)
    local tempObjNear = objTrans:GetChild(2)
    if objFar ~= tempObjFar then 
        if HelperFunc.IsNull(objFar) then
            objFar = tempObjFar
            objMid = tempObjMid
            objNear = tempObjNear
            objFarNext = _createNextObject(objFar, objFarNext)
            objMidNext = _createNextObject(objMid, objMidNext)
            objNearNext = _createNextObject(objNear, objNearNext)
        else
            objFar , objFarNext = objFarNext , objFar
            objMid , objMidNext = objMidNext , objMid
            objNear , objNearNext = objNearNext , objNear
        end
    end

    if not this.canLoop() then
        logWarn("地图结构错误，固定子节点丢失，不开启循环逻辑");
        return;
    end

    this.trans_far_check_point = Util.Lua_FindTransform(objFar, Str_CheckPoint)
    this.trans_far_next_check_point = Util.Lua_FindTransform(objFarNext, Str_CheckPoint) 
    this.trans_mid_check_point = Util.Lua_FindTransform(objMid, Str_CheckPoint)
    this.trans_mid_next_check_point = Util.Lua_FindTransform(objMidNext, Str_CheckPoint)
    this.trans_near_check_point = Util.Lua_FindTransform(objNear, Str_CheckPoint)
    this.trans_near_next_check_point = Util.Lua_FindTransform(objNearNext, Str_CheckPoint)


    if pointFarInit == nil then pointFarInit = objFar.transform.localPosition; end
    if pointMidInit == nil then pointMidInit = objMid.transform.localPosition; end
    if pointNearInit == nil then pointNearInit = objNear.transform.localPosition; end
    if pointFarNextInit == nil then pointFarNextInit = objFarNext.transform.localPosition end
    if pointMidNextInit == nil then pointMidNextInit = objMidNext.transform.localPosition end
    if pointNearNextInit == nil then pointNearNextInit = objNearNext.transform.localPosition end

    this.start()
end

--[[function  MapLinkCtr.loop()
    if objMap~=nil then
        objFar,  this.trans_far_check_point,  objFarNext,  this.trans_far_next_check_point, farLastCheckState  
            = this.layerLink(objFar, this.trans_far_check_point, objFarNext, this.trans_far_next_check_point, farLastCheckState);
        objMid, this.trans_mid_check_point,  objMidNext, this.trans_mid_next_check_point, midLastCheckState  
            = this.layerLink(objMid, this.trans_mid_check_point, objMidNext, this.trans_mid_next_check_point, midLastCheckState);
        objNear, this.trans_near_check_point, objNearNext, this.trans_near_next_check_point, nearLastCheckState 
            = this.layerLink(objNear, this.trans_near_check_point, objNearNext, this.trans_near_next_check_point, nearLastCheckState);
    end
end]]

function MapLinkCtr.GetDistance()
    return distance
end

function MapLinkCtr.reset()
    if this.canLoop() then
        this.stop();

        Util.Lua_SetLocalPositionXYZ(objFar, pointFarInit.x, pointFarInit.y, pointFarInit.z)
        Util.Lua_SetLocalPositionXYZ(objMid, pointMidInit.x, pointMidInit.y, pointMidInit.z)
        Util.Lua_SetLocalPositionXYZ(objNear, pointNearInit.x, pointNearInit.y, pointNearInit.z)
        Util.Lua_SetLocalPositionXYZ(objFarNext, pointFarNextInit.x, pointFarNextInit.y, pointFarNextInit.z)
        Util.Lua_SetLocalPositionXYZ(objMidNext, pointMidNextInit.x, pointMidNextInit.y, pointMidNextInit.z)
        Util.Lua_SetLocalPositionXYZ(objNearNext, pointNearNextInit.x, pointNearNextInit.y, pointNearNextInit.z)
        
        this.trans_far_check_point = Util.Lua_FindTransform(objFar, Str_CheckPoint)
        this.trans_far_next_check_point = Util.Lua_FindTransform(objFarNext, Str_CheckPoint)
        this.trans_mid_check_point = Util.Lua_FindTransform(objMid, Str_CheckPoint)
        this.trans_mid_next_check_point = Util.Lua_FindTransform(objMidNext, Str_CheckPoint)
        this.trans_near_check_point = Util.Lua_FindTransform(objNear, Str_CheckPoint)
        this.trans_near_next_check_point = Util.Lua_FindTransform(objNearNext, Str_CheckPoint)

        this.start();

    end
end

function MapLinkCtr.setPosition(offsetX)

    local function _setPos(go,nextGo,initPoint)
        local leftTr = Util.Lua_FindTransform(go, Str_StartPoint)
        local rightTr = Util.Lua_FindTransform(go, Str_EndPoint)

        local rposx,posy,posz = Util.Lua_GetLocalPositionXYZ(rightTr,0,0,0);
        local lposx,posy,posz = Util.Lua_GetLocalPositionXYZ(leftTr,0,0,0);
        local offset = rposx - lposx;
        local count =Mathf.Floor(offsetX/offset);
        if count>0 then
            local x,y,z = Util.Lua_GetLocalPositionXYZ(go.transform,0,0,0);
            x = initPoint.x + offset* count;
            Util.Lua_SetLocalPositionXYZ(go,x,y,z);
            this.setNextPos(go,nextGo);
        end
    end

    if this.canLoop() then
        _setPos(objFar,objFarNext,pointFarInit);
        _setPos(objMid,objMidNext,pointMidInit);
        _setPos(objNear,objNearNext,pointNearInit);
    end
end

function MapLinkCtr.canLoop()
    local function _check(go)
        if(HelperFunc.IsNull(go) or HelperFunc.IsNull(go.transform)) then
            return false
        end

        return Util.Lua_FindTransform(go, Str_StartPoint) ~= nil 
            and Util.Lua_FindTransform(go, Str_EndPoint) ~= nil 
            and Util.Lua_FindTransform(go, Str_CheckPoint) ~= nil
    end
    return _check(objFar) and _check(objMid) and _check(objNear);
end

function MapLinkCtr.stop()
    farLastCheckState = false;
    midLastCheckState = false;
    nearLastCheckState = false;
    if funcLoop~=nil then
        UpdateBeat:RemoveListener(funcLoop);
        funcLoop = nil;
    end
end

function MapLinkCtr.start()
    this.stop();
    --funcLoop = UpdateBeat:Add(this.loop,this);
    --UpdateBeat:AddListener(funcLoop);
end

function MapLinkCtr.setNextPos(go, nextGo) 
    local goEnd = Util.Lua_FindGameObject(go, Str_EndPoint)
    local cloneStart = Util.Lua_FindGameObject(nextGo, Str_StartPoint)

    local vec = goEnd.transform:TransformPoint(Vector3.zero);
    vec = cloneStart.transform:InverseTransformPoint(vec);
    local nextPosx,nextPosy,nextPosz = Util.Lua_GetLocalPositionXYZ(nextGo, 0, 0, 0);
    local goPosx, goPosy, goPosz = Util.Lua_GetLocalPositionXYZ(go, 0, 0, 0);
    Util.Lua_SetLocalPositionXYZ(nextGo, nextPosx + vec.x, goPosy, goPosz);
end

local cacheviewportPoint = Vector3.New(0,0,0)
function MapLinkCtr.layerLink(go, trans_check_point, nextGo, nexttrans_check_point, visibleState)
    local x, y, z = Util.Lua_GetPositionXYZ(trans_check_point, 0, 0, 0)
    cacheviewportPoint.x,cacheviewportPoint.y,cacheviewportPoint.z 
        = Util.Lua_GetWorldToViewportPointXYZ(camCamera,x,y,z,0,0,0)
    local newVisibleState = cacheviewportPoint.x>0 and cacheviewportPoint.x<1;
    if newVisibleState and not visibleState then
        local nextGox,nextGoy,nextGoz = Util.Lua_GetLocalPositionXYZ(nextGo,0,0,0);
        local gox,goy,goz = Util.Lua_GetLocalPositionXYZ(go,0,0,0);
        if nextGox< gox then
            this.setNextPos(go, nextGo);
        end
        local temp = go
        go = nextGo
        nextGo = temp

        temp = trans_check_point
        trans_check_point = nexttrans_check_point
        nexttrans_check_point = temp

        local x, y, z = Util.Lua_GetPositionXYZ(trans_check_point, 0, 0, 0)
        cacheviewportPoint.x, cacheviewportPoint.y, cacheviewportPoint.z = Util.Lua_GetWorldToViewportPointXYZ(camCamera,x,y,z,0,0,0)
        newVisibleState = cacheviewportPoint.x>0 and cacheviewportPoint.x<1;
        visibleState = newVisibleState;
    else
        visibleState = newVisibleState;
    end
    return go, trans_check_point, nextGo, nexttrans_check_point, visibleState;
end

function MapLinkCtr.Destroy()
    MapLinkCtr.stop()

    this.trans_far_check_point = nil
    this.trans_far_next_check_point = nil
    this.trans_mid_check_point = nil
    this.trans_mid_next_check_point = nil
    this.trans_near_check_point = nil
    this.trans_near_next_check_point = nil

    if not HelperFunc.IsNull( objFarNext) then
        destroy(objFarNext.gameObject)
    end
    if not HelperFunc.IsNull( objNearNext) then
        destroy(objNearNext.gameObject)
    end
    if not HelperFunc.IsNull( objMidNext) then
        destroy(objMidNext.gameObject)
    end
    if not HelperFunc.IsNull( objFar) then
        Util.Lua_SetLocalPositionXYZ(objFar,0,0,0);
    end
    if not HelperFunc.IsNull( objNear) then
        Util.Lua_SetLocalPositionXYZ(objNear,0,0,0);
    end
    if not HelperFunc.IsNull( objMid) then
        Util.Lua_SetLocalPositionXYZ(objMid,0,0,0);
    end 
    camCamera = nil;
    objMap = nil;
    objFar = nil;
    objFarNext = nil;
    farLastCheckState = nil;
    pointFarInit = nil;
    pointFarNextInit = nil
    objMid = nil;
    objMidNext = nil;
    midLastCheckState = nil;
    pointMidInit = nil;
    pointMidNextInit = nil
    objNear = nil;
    objNearNext = nil;
    nearLastCheckState = nil;
    pointNearInit = nil;
    pointNearNextInit = nil
end

